package com.hup.minicontroller.server.activity;

import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.AbsoluteSizeSpan;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.util.Consumer;

import com.hup.minicontroller.common.constant.NetConstant.ConnectType;
import com.hup.minicontroller.common.framework.SubThreadHandler;
import com.hup.minicontroller.server.R;
import com.hup.minicontroller.server.ServerApplication;
import com.hup.minicontroller.server.androidService.AppService;
import com.hup.minicontroller.server.androidService.MyAccessibilityService;
import com.hup.minicontroller.server.auth.FloaterAuthForCFS;
import com.hup.minicontroller.server.auth.MediaProjectionAuthForSIS;
import com.hup.minicontroller.server.model.AppState;
import com.hup.minicontroller.server.model.ControlConfig;
import com.hup.minicontroller.server.mvp.ICursorFloaterView;
import com.hup.minicontroller.server.mvp.IMainView;
import com.hup.minicontroller.server.mvp.IServerHandler;
import com.hup.minicontroller.server.mvp.IServerHandler.ServerHandlerList;
import com.hup.minicontroller.server.service.MainService;
import com.hup.minicontroller.server.view.ClientItemAdapter;
import com.hup.minicontroller.server.view.MainForm;

import java.util.Objects;

public class MainActivity extends AppCompatActivity implements IMainView {
    private static final String TAG = MainActivity.class.getSimpleName();
    private static final String KEY_ACQUIRE_MEDIA_PROJECTION = "AcquireMediaProjection";

    private MainForm form;
    private ClientItemAdapter clientItemAdapter;

    private AppState appState;
    private SubThreadHandler subThreadHandler;
    private ServerHandlerList serverHandlers;
    private int smallFont;

    private boolean isForeground;
    private NetSpeedRunner netSpeedRunner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (!isTaskRoot()) {
            finish();
            return;
        }

        Log.i(TAG, "onCreate: " + isTaskRoot());
        appState = ServerApplication.getBean(MainService.class).getAppState();
        subThreadHandler = ServerApplication.getBean(SubThreadHandler.class);
        serverHandlers = ServerApplication.getBean(ServerHandlerList.class);
        netSpeedRunner = new NetSpeedRunner();
        smallFont = getResources().getDimensionPixelSize(R.dimen.small_font);

        setContentView(MainForm.RESOURCE_ID);
        Objects.requireNonNull(getSupportActionBar()).setTitle(R.string.main_txt_title);
        form = new MainForm(this);
        if (BluetoothAdapter.getDefaultAdapter() == null) form.cbEnableBluetooth.setEnabled(false);
        clientItemAdapter = new ClientItemAdapter();
        form.lvClient.setAdapter(clientItemAdapter);
        initListener();
        ServerApplication.putBean(IMainView.class, this);
        Log.i(TAG, "=====  已打开" + getClass().getSimpleName());

        if (savedInstanceState != null && savedInstanceState.getBoolean(KEY_ACQUIRE_MEDIA_PROJECTION, false)) {
            MediaProjectionAuthForSIS.acquireMediaProjectionForService(this);
        }
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        Log.i(TAG, "onRestoreInstanceState: ");
        //super.onRestoreInstanceState(savedInstanceState);//坑到家!转屏后onCreate后会传递错误的值给SeekBar
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume: ");
        isForeground = true;
        updateViewByModel();
        form.btnExit.post(netSpeedRunner);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause: ");
        isForeground = false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy: ");
        ServerApplication.removeBean(IMainView.class);
    }

    private void initListener() {
        form.cbEnableLan.setOnCheckedChangeListener((v, isChecked) -> {
            if (!v.isPressed()) return;//过滤setChecked事件
            //禁用组件并通知server,直到server刷新config后,才通知view刷新组件状态
            Log.i(TAG, "cbEnableLan: " + isChecked);
            v.setEnabled(false);
            subThreadHandler.post(() -> serverHandlers.forEach((Consumer<IServerHandler>)
                    i -> i.switchServer(ConnectType.LAN, isChecked)));
        });
        form.cbEnableBluetooth.setOnCheckedChangeListener((v, isChecked) -> {
            if (!v.isPressed()) return;
            Log.i(TAG, "cbEnableBluetooth: " + isChecked);
            v.setEnabled(false);
            subThreadHandler.post(() -> serverHandlers.forEach((Consumer<IServerHandler>)
                    i -> i.switchServer(ConnectType.BLUETOOTH, isChecked)));
        });
        form.btnExit.setOnClickListener(v -> {
            finish();
            ServerApplication.getBean(MainService.class).doTerminate(true);
        });
        form.cbShowCursor.setOnCheckedChangeListener((v, isChecked) -> {
            if (!v.isPressed()) return;
            Log.i(TAG, "cbShowCursor: " + isChecked);
            appState.getControlConfig().setShowCursor(isChecked);
            //不需要通知客户端
            ServerApplication.getBean(ICursorFloaterView.class).onUpdateShowCursor();
        });
        form.cbEnableControl.setOnCheckedChangeListener((v, isChecked) -> {
            if (!v.isPressed()) return;
            Log.i(TAG, "cbEnableControl: " + isChecked);
            appState.getControlConfig().setEnableControl(isChecked);
            onControlConfigChanged();
            subThreadHandler.post(() -> serverHandlers.onControlConfigChanged());
        });
        form.btnGotoAccessibility.setOnClickListener(v -> {
            Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
            startActivity(intent);
        });
        form.cbEnableScreen.setOnCheckedChangeListener((v, isChecked) -> {
            if (!v.isPressed()) return;
            Log.i(TAG, "cbEnableScreen: " + isChecked);
            //马上更新config,并通知server
            appState.getControlConfig().setEnableScreen(isChecked);
            onControlConfigChanged();
            subThreadHandler.post(() -> serverHandlers.onControlConfigChanged());
        });
        form.sbFps.setValueChangedListener((value, fromUser) -> {
            if (!fromUser) return;
            Log.i(TAG, "sbFps: " + value);
            appState.getControlConfig().setFps(value);
            subThreadHandler.post(() -> serverHandlers.onControlConfigChanged());
        });
        form.sbScreenSize.setValueChangedListener((value, fromUser) -> {
            if (!fromUser) return;
            Log.i(TAG, "sbScreenSize: " + value);
            appState.getControlConfig().setScreenSize(value);
            subThreadHandler.post(() -> serverHandlers.onControlConfigChanged());
        });
        form.sbScreenQuality.setValueChangedListener((value, fromUser) -> {
            if (!fromUser) return;
            Log.i(TAG, "sbScreenQuality: " + value);
            appState.getControlConfig().setScreenQuality(value);
            subThreadHandler.post(() -> serverHandlers.onControlConfigChanged());
        });
    }

    private void updateViewByModel() {
        //总开关
        form.cbEnableLan.setChecked(appState.isStartedLan());
        form.cbEnableBluetooth.setChecked(appState.isStartedBluetooth());
        updateDeviceState();//设备状态
        onControlConfigChanged();//控制配置
        onClientChanged();//客户端
    }

    private void updateDeviceState() {
        StringBuilder sb = new StringBuilder();
        if (appState.isWifiOn()) sb.append("wifi已连接\n");
        if (appState.isApOn()) sb.append("热点已开启\n");
        if (appState.isBluetoothOn()) sb.append("蓝牙已开启\n");
        if (sb.length() != 0) sb.deleteCharAt(sb.length() - 1);
        form.txtDeviceState.setText(sb.toString());
    }


    private void setLineWrapText(TextView textView, @StringRes int resId) {
        String str = getString(resId);
        SpannableString spannable = new SpannableString(new SpannableString(str));
        int wrapIndex = str.indexOf('\n');
        spannable.setSpan(new AbsoluteSizeSpan(smallFont), wrapIndex, spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        textView.setText(spannable);
    }

    @Override
    public void onNetServerStateChanged(ConnectType connectType) {
        if (!isForeground) return;
        Log.i(TAG, "onNetServerStateChanged: " + connectType);
        runOnUiThread(() -> {
            if (ConnectType.LAN.equals(connectType)) {
                form.cbEnableLan.setEnabled(true);
                form.cbEnableLan.setChecked(appState.isStartedLan());
                onClientChanged();
            } else if (ConnectType.BLUETOOTH.equals(connectType)) {
                form.cbEnableBluetooth.setEnabled(true);
                form.cbEnableBluetooth.setChecked(appState.isStartedBluetooth());
                onClientChanged();
            }
            if (appState.isStartedLan() || appState.isStartedBluetooth()) form.btnExit.post(netSpeedRunner);
        });
    }

    @Override
    public void onControlConfigChanged() {
        if (!isForeground) return;
        runOnUiThread(() -> {
            ControlConfig controlConfig = appState.getControlConfig();
            Log.i(TAG, "onControlConfigChanged: " + controlConfig);
            form.cbShowCursor.setChecked(controlConfig.isShowCursor());
            form.cbEnableControl.setChecked(controlConfig.isEnableControl());
            if (controlConfig.isEnableControl()) {
                form.btnGotoAccessibility.setVisibility(View.VISIBLE);
                if (ServerApplication.getBeanNullable(MyAccessibilityService.class) != null) {
                    form.btnGotoAccessibility.setText(R.string.main_accessibility_started);
                } else {
                    setLineWrapText(form.btnGotoAccessibility, R.string.main_accessibility_stopped);
                }
            } else {
                form.btnGotoAccessibility.setVisibility(View.GONE);
            }

            boolean canEnableScreen = controlConfig.isCanEnableScreen();
            boolean enableScreen = controlConfig.isEnableScreen();
            form.cbEnableScreen.setEnabled(canEnableScreen);
            form.cbEnableScreen.setChecked(enableScreen);
            form.sbFps.setVisibility(canEnableScreen && enableScreen ? View.VISIBLE : View.GONE);
            form.sbScreenSize.setVisibility(canEnableScreen && enableScreen ? View.VISIBLE : View.GONE);
            form.sbScreenQuality.setVisibility(canEnableScreen && enableScreen ? View.VISIBLE : View.GONE);
            if (canEnableScreen && enableScreen) {
                form.sbFps.setValue(controlConfig.getFps());
                form.sbScreenSize.setValue(controlConfig.getScreenSize());
                form.sbScreenQuality.setValue(controlConfig.getScreenQuality());
            }
        });
    }

    @Override
    public void onClientChanged() {
        if (!isForeground) return;
        Log.i(TAG, "onClientChanged: ");
        runOnUiThread(() -> appState.accessClient(onlineClientSessions -> {
            Log.i(TAG, "onClientChanged: in accessClient");
            clientItemAdapter.setData(onlineClientSessions);
        }));
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (!MediaProjectionAuthForSIS.handleActivityResult(requestCode, resultCode, data, this)
                && !FloaterAuthForCFS.handleActivityResult(requestCode, resultCode, data, this)) {
            Log.i(TAG, "onActivityResult: 其他请求:" + requestCode);
        }
    }

    @Override
    public SurfaceView switchSurfaceViewOfScreenCapture(boolean startReceive) {
        runOnUiThread(() -> form.svScreenCapture.setVisibility(startReceive ? View.VISIBLE : View.GONE));
        return form.svScreenCapture;
    }

    public static void startAndAcquireMediaProjection() {
        Log.i(TAG, "startAndAcquireMediaProjection: ");
        Context context = ServerApplication.getBean(AppService.class);
        Intent intent = new Intent(context, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(KEY_ACQUIRE_MEDIA_PROJECTION, true);
        context.startActivity(intent);
    }

    /**
     * 更新网速功能
     */
    private class NetSpeedRunner implements Runnable {

        @Override
        public void run() {
            if (!isForeground) return;
            StringBuilder sb = new StringBuilder();
            serverHandlers.forEach((Consumer<IServerHandler>) i -> i.getSpeedText(sb));
            if (sb.length() > 0) {
                form.txtNetSpeed.setVisibility(View.VISIBLE);
                form.txtNetSpeed.setText(sb.toString());
                form.btnExit.postDelayed(this, 1000);
            } else {
                //无服务端启动,停止刷新,隐藏控件
                form.txtNetSpeed.setVisibility(View.GONE);
            }
        }
    }

}
